﻿// TrayS.cpp : 定义应用程序的入口点。
//
#ifdef _WIN64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif

#include "framework.h"
#include "TrayS.h"
#include <commctrl.h>
#include <Commdlg.h>
#include <Shellapi.h>

#define MAX_LOADSTRING 100
#define  WM_IAWENTRAY 8899//通知栏消息
// 全局变量:
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
HWND hMain;
HICON iMain;
HANDLE hMutex;
WCHAR szShellTray[] = L"Shell_TrayWnd";
WCHAR szSecondaryTray[] = L"Shell_SecondaryTrayWnd";
WCHAR szSubKey[]= L"SOFTWARE\\TrayS";
WCHAR szAppName[] = L"TrayS";
// 此代码模块中包含的函数的前向声明:
BOOL                InitInstance(HINSTANCE, int);
INT_PTR CALLBACK    MainProc(HWND, UINT, WPARAM, LPARAM);
BOOL AutoRun(BOOL GetSet, BOOL bAuto);
typedef enum _WINDOWCOMPOSITIONATTRIB
{
	WCA_UNDEFINED = 0,
	WCA_NCRENDERING_ENABLED = 1,
	WCA_NCRENDERING_POLICY = 2,
	WCA_TRANSITIONS_FORCEDISABLED = 3,
	WCA_ALLOW_NCPAINT = 4,
	WCA_CAPTION_BUTTON_BOUNDS = 5,
	WCA_NONCLIENT_RTL_LAYOUT = 6,
	WCA_FORCE_ICONIC_REPRESENTATION = 7,
	WCA_EXTENDED_FRAME_BOUNDS = 8,
	WCA_HAS_ICONIC_BITMAP = 9,
	WCA_THEME_ATTRIBUTES = 10,
	WCA_NCRENDERING_EXILED = 11,
	WCA_NCADORNMENTINFO = 12,
	WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
	WCA_VIDEO_OVERLAY_ACTIVE = 14,
	WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
	WCA_DISALLOW_PEEK = 16,
	WCA_CLOAK = 17,
	WCA_CLOAKED = 18,
	WCA_ACCENT_POLICY = 19,
	WCA_FREEZE_REPRESENTATION = 20,
	WCA_EVER_UNCLOAKED = 21,
	WCA_VISUAL_OWNER = 22,
	WCA_LAST = 23
} WINDOWCOMPOSITIONATTRIB;

typedef struct _WINDOWCOMPOSITIONATTRIBDATA
{
	WINDOWCOMPOSITIONATTRIB Attrib;
	PVOID pvData;
	SIZE_T cbData;
} WINDOWCOMPOSITIONATTRIBDATA;

typedef enum _ACCENT_STATE
{
	ACCENT_DISABLED = 0,
	ACCENT_ENABLE_GRADIENT = 1,
	ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
	ACCENT_ENABLE_BLURBEHIND = 3,
	ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
	ACCENT_INVALID_STATE = 5
} ACCENT_STATE;

typedef struct _ACCENT_POLICY
{
	ACCENT_STATE AccentState;
	DWORD AccentFlags;
	DWORD GradientColor;
	DWORD AnimationId;
} ACCENT_POLICY;

ACCENT_STATE aMode = ACCENT_ENABLE_TRANSPARENTGRADIENT;
DWORD dAlphaColor=0x00111111;
DWORD bAlpha = 255;
WCHAR szMode[] = L"StyleMode";
WCHAR szAlphaColor[] = L"AlphaColor";
WCHAR szAlpha[] = L"Alpha";
NOTIFYICONDATA nid;//通知栏传入结构
BOOL SetWindowCompositionAttribute(HWND, ACCENT_STATE, DWORD);//设置磨砂
BOOL GetWindowCompositionAttribute(HWND, ACCENT_POLICY *);//获取磨砂

INT_PTR CALLBACK    ColorButtonProc(HWND, UINT, WPARAM, LPARAM);//颜色按钮子类化过程
WNDPROC oldColorButtonPoroc;//原来的颜色按钮控件过程

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

	hMutex = CreateMutex(NULL, TRUE, L"_TrayS_");
	if (hMutex != NULL)
	{
		if (ERROR_ALREADY_EXISTS == GetLastError())
		{
			return 0;
		}
	}


    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_TRAYS, szWindowClass, MAX_LOADSTRING);
	iMain = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRAYS));
    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
	SendMessage(hMain, WM_SETICON, ICON_BIG, (LPARAM)(HICON)iMain);
	SendMessage(hMain, WM_SETICON, ICON_SMALL, (LPARAM)(HICON)iMain);
	HKEY pKey;
	DWORD dwDisposition;
	RegCreateKeyEx(HKEY_CURRENT_USER, szSubKey, NULL, NULL, REG_OPTION_NON_VOLATILE, NULL, NULL, &pKey, &dwDisposition);
	if (dwDisposition == REG_CREATED_NEW_KEY)
	{

	}
	else
	{
		if (pKey == 0)
			RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, NULL, KEY_ALL_ACCESS, &pKey);
		DWORD dType = REG_DWORD;
		DWORD cbData = sizeof(DWORD);
		RegQueryValueEx(pKey, szMode, NULL, &dType, (BYTE*)&aMode, &cbData);
		dType = REG_DWORD;
		cbData = sizeof(DWORD);
		RegQueryValueEx(pKey, szAlphaColor, NULL, &dType, (BYTE*)&dAlphaColor, &cbData);
		dType = REG_DWORD;
		cbData = sizeof(DWORD);
		RegQueryValueEx(pKey, szAlpha, NULL, &dType, (BYTE*)&bAlpha, &cbData);
		RegCloseKey(pKey);
	}
	if (aMode == ACCENT_DISABLED)
		CheckRadioButton(hMain, IDC_RADIO_DEFAULT, IDC_RADIO_ACRYLIC, IDC_RADIO_DEFAULT);
	else if (aMode == ACCENT_ENABLE_TRANSPARENTGRADIENT)
		CheckRadioButton(hMain, IDC_RADIO_DEFAULT, IDC_RADIO_ACRYLIC, IDC_RADIO_TRANSPARENT);
	else if (aMode == ACCENT_ENABLE_BLURBEHIND)
		CheckRadioButton(hMain, IDC_RADIO_DEFAULT, IDC_RADIO_ACRYLIC, IDC_RADIO_BLURBEHIND);
	else if (aMode == ACCENT_ENABLE_ACRYLICBLURBEHIND)
		CheckRadioButton(hMain, IDC_RADIO_DEFAULT, IDC_RADIO_ACRYLIC, IDC_RADIO_ACRYLIC);	
	SendDlgItemMessage(hMain, IDC_SLIDER_ALPHA, TBM_SETRANGE, 0, MAKELPARAM(0, 255));
	SendDlgItemMessage(hMain, IDC_SLIDER_ALPHA, TBM_SETPOS, TRUE, bAlpha);
	SendDlgItemMessage(hMain, IDC_SLIDER_ALPHA_B, TBM_SETRANGE, 0, MAKELPARAM(0, 255));
	BYTE bAlphaB = dAlphaColor >> 24;
	SendDlgItemMessage(hMain, IDC_SLIDER_ALPHA_B, TBM_SETPOS, TRUE, bAlphaB);
	SendDlgItemMessage(hMain, IDC_CHECK_AUTORUN, BM_SETCHECK, AutoRun(FALSE, FALSE), NULL);
	oldColorButtonPoroc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hMain,IDC_BUTTON_COLOR), GWLP_WNDPROC, (LONG_PTR)ColorButtonProc);
	//////////////////////////////////////////////////////////////////////////////////设置通知栏图标
	nid.cbSize = sizeof NOTIFYICONDATA;
	nid.uID = WM_IAWENTRAY;
	nid.hWnd = hMain;
	nid.hIcon = iMain;
	nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
	nid.uCallbackMessage = WM_IAWENTRAY;
	LoadString(hInst, IDS_TIPS, nid.szTip, 88);
	::Shell_NotifyIcon(NIM_ADD, &nid);
    MSG msg;
    // 主消息循环:
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		if (!IsDialogMessage(hMain, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	Shell_NotifyIcon(NIM_DELETE, &nid);
	CloseHandle(hMutex);
	DestroyWindow(hMain);
	DestroyIcon(iMain);
    return (int) msg.wParam;
}


//
//   函数: InitInstance(HINSTANCE, int)
//
//   目标: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中，我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   hMain = ::CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)MainProc);
   if (!hMain)
   {
      return FALSE;
   }   
   ShowWindow(hMain, SW_HIDE);
   UpdateWindow(hMain);
   SetTimer(hMain, 3, 33, NULL);
   SetTimer(hMain, 11, 1000, NULL);
   return TRUE;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK MainProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;
	case WM_TIMER:
	{
		if (wParam == 11)
		{
			KillTimer(hDlg, wParam);
			HANDLE hProcess = GetCurrentProcess();
			SetProcessWorkingSetSize(hProcess, -1, -1);
//			EmptyWorkingSet(hProcess);
		}
		else if (wParam == 3)
		{
			HWND hTray = FindWindow(szShellTray, NULL);
			SetWindowCompositionAttribute(hTray, aMode, dAlphaColor);
			LONG_PTR exStyle = GetWindowLongPtr(hTray, GWL_EXSTYLE);
			exStyle |= WS_EX_LAYERED;
			SetWindowLongPtr(hTray, GWL_EXSTYLE,exStyle);
			SetLayeredWindowAttributes(hTray, 0, bAlpha, LWA_ALPHA);
			HWND hSTray = FindWindow(szSecondaryTray, NULL);
			if (hSTray)
			{
				SetWindowCompositionAttribute(hSTray, aMode, dAlphaColor);
				exStyle = GetWindowLongPtr(hSTray, GWL_EXSTYLE);
				exStyle |= WS_EX_LAYERED;
				SetWindowLongPtr(hSTray, GWL_EXSTYLE, exStyle);
				SetLayeredWindowAttributes(hSTray, 0, bAlpha, LWA_ALPHA);
			}
		}
	}
		break;
	case WM_IAWENTRAY://////////////////////////////////////////////////////////////////////////////////通知栏左右键处理
	{
		if (wParam == WM_IAWENTRAY)
		{
			if (lParam == WM_LBUTTONDOWN|| lParam == WM_RBUTTONDOWN)
				ShowWindow(hDlg, SW_SHOW);
		}
		break;
	}
	case WM_HSCROLL://////////////////////////////////////////////////////////////////////////////////透明度处理
	{
		HWND hSlider = GetDlgItem(hDlg, IDC_SLIDER_ALPHA);
		HWND hSliderB = GetDlgItem(hDlg, IDC_SLIDER_ALPHA_B);
		if (hSlider == (HWND)lParam)
		{
			bAlpha = (int)SendDlgItemMessage(hDlg, IDC_SLIDER_ALPHA, TBM_GETPOS, 0, 0);
//			SetLayeredWindowAttributes(hFocus, 0, bFocusAlpha, LWA_ALPHA);
		}
		else if (hSliderB == (HWND)lParam)
		{
			DWORD bAlphaB= (int)SendDlgItemMessage(hDlg, IDC_SLIDER_ALPHA_B, TBM_GETPOS, 0, 0);
			bAlphaB = bAlphaB << 24;
			dAlphaColor = bAlphaB + (dAlphaColor & 0xffffff);
		}
		break;
	}
    case WM_COMMAND:
		if (LOWORD(wParam) >= IDC_RADIO_DEFAULT && LOWORD(wParam) <= IDC_RADIO_ACRYLIC)
		{
			if (IsDlgButtonChecked(hDlg, IDC_RADIO_DEFAULT))
				aMode = ACCENT_DISABLED;
			else if (IsDlgButtonChecked(hDlg, IDC_RADIO_TRANSPARENT))
				aMode = ACCENT_ENABLE_TRANSPARENTGRADIENT;
			else if (IsDlgButtonChecked(hDlg, IDC_RADIO_BLURBEHIND))
				aMode = ACCENT_ENABLE_BLURBEHIND;
			else if (IsDlgButtonChecked(hDlg, IDC_RADIO_ACRYLIC))
				aMode = ACCENT_ENABLE_ACRYLICBLURBEHIND;
		}
		if (LOWORD(wParam) == IDOK)
		{
			HKEY pKey;
			RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, NULL, KEY_ALL_ACCESS, &pKey);
			if (pKey)
			{
				RegSetValueEx(pKey, szMode, NULL, REG_DWORD, (BYTE*)&aMode, sizeof(aMode));
				RegSetValueEx(pKey, szAlphaColor, NULL, REG_DWORD, (BYTE*)&dAlphaColor, sizeof(dAlphaColor));
				RegSetValueEx(pKey, szAlpha, NULL, REG_DWORD, (BYTE*)&bAlpha, sizeof(bAlpha));
				RegCloseKey(pKey);
			}
			if (SendDlgItemMessage(hDlg, IDC_CHECK_AUTORUN, BM_GETCHECK, NULL, NULL) == BST_CHECKED)
				AutoRun(TRUE, TRUE);
			else
				AutoRun(TRUE, FALSE);
			ShowWindow(hDlg, SW_HIDE);
			SetTimer(hMain, 11, 1000, NULL);
		}
		else if(LOWORD(wParam) == IDCANCEL)
        {			
			ShowWindow(hDlg, SW_HIDE);
			SetTimer(hMain, 11, 1000, NULL);
            return (INT_PTR)TRUE;
        }
		else if (LOWORD(wParam) == IDC_CLOSE)
		{
			PostQuitMessage(0);
		}
		else if (LOWORD(wParam) == IDC_BUTTON_COLOR)
		{
			COLORREF rgb = RGB(255, 255, 255);
			CHOOSECOLOR stChooseColor;
			stChooseColor.lStructSize = sizeof(CHOOSECOLOR);
			stChooseColor.hwndOwner = hDlg;
			stChooseColor.rgbResult = dAlphaColor;
			stChooseColor.lpCustColors = (LPDWORD)&dAlphaColor;
			stChooseColor.Flags = CC_RGBINIT | CC_FULLOPEN;
			stChooseColor.lCustData = 0;
			stChooseColor.lpfnHook = NULL;
			stChooseColor.lpTemplateName = NULL;
			if (ChooseColor(&stChooseColor))
			{
				dAlphaColor = stChooseColor.rgbResult;
				DWORD bAlphaB = (int)SendDlgItemMessage(hDlg, IDC_SLIDER_ALPHA_B, TBM_GETPOS, 0, 0);
				bAlphaB = bAlphaB << 24;
				dAlphaColor = bAlphaB + (dAlphaColor & 0xffffff);
				::InvalidateRect(GetDlgItem(hMain, IDC_BUTTON_COLOR), NULL, FALSE);
			}
		}
        break;
    }
    return (INT_PTR)FALSE;
}
typedef BOOL(WINAPI*pfnSetWindowCompositionAttribute)(HWND, struct _WINDOWCOMPOSITIONATTRIBDATA*);
BOOL SetWindowCompositionAttribute(HWND hWnd, ACCENT_STATE mode, DWORD AlphaColor)
{
	BOOL ret = FALSE;
	HMODULE hUser = GetModuleHandle(L"user32.dll");
	if (hUser)
	{
		pfnSetWindowCompositionAttribute setWindowCompositionAttribute = (pfnSetWindowCompositionAttribute)GetProcAddress(hUser, "SetWindowCompositionAttribute");
		if (setWindowCompositionAttribute)
		{
			ACCENT_POLICY accent = { mode, 0, AlphaColor, 0 };
			_WINDOWCOMPOSITIONATTRIBDATA data;
			data.Attrib = WCA_ACCENT_POLICY;
			data.pvData = &accent;
			data.cbData = sizeof(accent);
			ret = setWindowCompositionAttribute(hWnd, &data);
		}
	}
	return ret;
}
typedef BOOL(WINAPI*pfnGetWindowCompositionAttribute)(HWND, struct _WINDOWCOMPOSITIONATTRIBDATA*);
BOOL GetWindowCompositionAttribute(HWND hWnd, ACCENT_POLICY * accent)
{
	BOOL ret = FALSE;
	HMODULE hUser = GetModuleHandle(L"user32.dll");
	if (hUser)
	{
		pfnGetWindowCompositionAttribute getWindowCompositionAttribute = (pfnGetWindowCompositionAttribute)GetProcAddress(hUser, "GetWindowCompositionAttribute");
		if (getWindowCompositionAttribute)
		{
			_WINDOWCOMPOSITIONATTRIBDATA data;
			ACCENT_POLICY acc[2];
			data.Attrib = WCA_ACCENT_POLICY;
			data.pvData = acc;
			data.cbData = sizeof ACCENT_POLICY * 2;
			ret = getWindowCompositionAttribute(hWnd, &data);
		}
	}
	return ret;
}
BOOL AutoRun(BOOL GetSet, BOOL bAuto)//读取、设置开机启动、关闭开机启动
{
	BOOL ret = FALSE;
	WCHAR sFileName[MAX_PATH];
	GetModuleFileName(NULL, sFileName, MAX_PATH);
	HKEY pKey;
	RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", NULL, KEY_ALL_ACCESS, &pKey);
	if (!pKey)
		RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", NULL, KEY_ALL_ACCESS, &pKey);
	if (pKey)
	{
		if (GetSet)
		{
			if (bAuto)
			{
				RegSetValueEx(pKey, szAppName, NULL, REG_SZ, (BYTE*)sFileName, MAX_PATH * sizeof(WCHAR));
			}
			else
			{
				RegDeleteValue(pKey, szAppName);
			}
			ret = TRUE;
		}
		else
		{
			WCHAR nFileName[MAX_PATH];
			DWORD cbData = MAX_PATH * sizeof WCHAR;
			DWORD dType = REG_SZ;
			if (RegQueryValueEx(pKey, szAppName, NULL, &dType, (LPBYTE)nFileName, &cbData) == ERROR_SUCCESS)
			{
				if (wcscmp(sFileName, nFileName) == 0)
					ret = TRUE;
				else
					ret = FALSE;
			}
		}
		RegCloseKey(pKey);
	}
	return ret;
}
INT_PTR CALLBACK ColorButtonProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)//颜色按钮控件右键处理
{
	switch (message)
	{
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		RECT rc;
		GetClientRect(hWnd, &rc);
		HBRUSH hb;
		hb = CreateSolidBrush(dAlphaColor&0xffffff);
		FillRect(hdc, &rc, hb);
		DeleteObject(hb);
		EndPaint(hWnd, &ps);
		return TRUE;
	}
	}
	return CallWindowProc(oldColorButtonPoroc, hWnd, message, wParam, lParam);
}